package com.pcafs.manage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.pcafs.common.core.domain.TreeSelect;
import com.pcafs.common.core.domain.entity.PcafsDatabase;
import com.pcafs.common.utils.SecurityUtils;
import com.pcafs.manage.bo.PcafsDatabaseAddBo;
import com.pcafs.manage.bo.PcafsDatabaseEditBo;
import com.pcafs.manage.bo.PcafsDatabaseQueryBo;
import com.pcafs.manage.domain.PcafsDefaultField;
import com.pcafs.manage.mapper.PcafsDatabaseMapper;
import com.pcafs.manage.mapper.PcafsFieldMapper;
import com.pcafs.manage.service.IPcafsDatabaseService;
import com.pcafs.manage.vo.PcafsDatabaseVo;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 财务数据仓Service业务层处理
 *
 * @author pcafs
 * @date 2022-05-02
 */
@Service
@AllArgsConstructor
public class PcafsDatabaseServiceImpl extends ServiceImpl<PcafsDatabaseMapper, PcafsDatabase> implements IPcafsDatabaseService {

    private final PcafsFieldMapper pcafsFieldMapper;

    @Override
    public PcafsDatabaseVo queryById(Long id) {
        PcafsDatabase db = this.baseMapper.selectById(id);
        return BeanUtil.toBean(db, PcafsDatabaseVo.class);
    }

    @Override
    public List<PcafsDatabaseVo> queryList(PcafsDatabaseQueryBo bo) {
        LambdaQueryWrapper<PcafsDatabase> lqw = Wrappers.lambdaQuery();
        lqw.like(StrUtil.isNotBlank(bo.getTabName()), PcafsDatabase::getTabName, bo.getTabName());
        lqw.eq(StrUtil.isNotBlank(bo.getTabNameEn()), PcafsDatabase::getTabNameEn, bo.getTabNameEn());
        lqw.eq(StrUtil.isNotBlank(bo.getCreater()), PcafsDatabase::getCreater, bo.getCreater());
        lqw.eq(bo.getCreateTime() != null, PcafsDatabase::getCreateTime, bo.getCreateTime());
        lqw.eq(bo.getPid() != null, PcafsDatabase::getPid, bo.getPid());
        return entity2Vo(this.list(lqw));
    }

    /**
     * 实体类转化成视图对象
     *
     * @param collection 实体类集合
     * @return
     */
    private List<PcafsDatabaseVo> entity2Vo(Collection<PcafsDatabase> collection) {
        List<PcafsDatabaseVo> voList = collection.stream()
                .map(any -> BeanUtil.toBean(any, PcafsDatabaseVo.class))
                .collect(Collectors.toList());
        if (collection instanceof Page) {
            Page<PcafsDatabase> page = (Page<PcafsDatabase>) collection;
            Page<PcafsDatabaseVo> pageVo = new Page<>();
            BeanUtil.copyProperties(page, pageVo);
            pageVo.addAll(voList);
            voList = pageVo;
        }
        return voList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByAddBo(PcafsDatabaseAddBo bo) {
        PcafsDatabase add = BeanUtil.toBean(bo, PcafsDatabase.class);
        add.setCreater(SecurityUtils.getUserId());
        validEntityBeforeSave(add);
        Integer count = this.baseMapper.getByName(bo.getTabName());
        if(count > 0){
            return false;
        }
        String tabName = "pcafs_" + DateUtil.current();
        add.setTabNameEn(tabName);
        boolean isOk = this.save(add);
        if (isOk) {
            this.createTab(tabName) ;
        }
        return isOk;
    }

    /**
     * 创建表
     *
     * @param tabName:
     * @Author hyh
     * @Date 14:57 2022/5/5
     **/
    @Transactional(rollbackFor = Exception.class)
    public void createTab(String tabName) {

        // 查询默认字段
        List<PcafsDefaultField> fields = pcafsFieldMapper.queryDefaultField();

        StringBuffer buffer = new StringBuffer();
        buffer.append("CREATE TABLE " + tabName + "(");

        for (PcafsDefaultField field : fields) {
            String fieldEn = field.getFieldEn();
            String fieldType = field.getFieldType();
            Integer fieldLength = field.getFieldLength();
            Integer fieldDecimalLength = field.getFieldDecimalLength();
            Integer isNotNull = field.getIsNotNull();
            String defaultValue = field.getDefaultValue();
            // 主键
            if (field.getIsKey() == 0) {
                buffer.append(fieldEn + " " + fieldType + "(" + fieldLength + ")" + " NOT NULL primary key");
                if (field.getIsAutoIncrement() == 0) {
                    buffer.append(" AUTO_INCREMENT,");
                }
                // 时间
            } else if (fieldType.equals("datetime")) {
                if (isNotNull == 0) {
                    // 有默认值 必定不是 null
                    if (StrUtil.isNotBlank(defaultValue)) {
                        buffer.append(fieldEn + " " + fieldType + " NOT NULL DEFAULT '" + defaultValue + "',");
                    } else {
                        buffer.append(fieldEn + " " + fieldType + " NOT NULL,");
                    }
                } else {
                    buffer.append(fieldEn + " " + fieldType + ",");
                }
                // 其他
            } else if (fieldType.equals("double")) {
                if (isNotNull == 0) {
                    // 有默认值 必定不是 null
                    if (StrUtil.isNotBlank(defaultValue)) {
                        buffer.append(fieldEn + " " + fieldType + "(" + fieldLength + "," + fieldDecimalLength + ")" + " NOT NULL DEFAULT '" + defaultValue + "',");
                    } else {
                        buffer.append(fieldEn + " " + fieldType + "(" + fieldLength + "," + fieldDecimalLength + ") NOT NULL,");
                    }
                } else {
                    buffer.append(fieldEn + " " + fieldType + "(" + fieldLength + "," + fieldDecimalLength + "),");
                }
            } else {
                if (isNotNull == 0) {
                    // 有默认值 必定不是 null
                    if (StrUtil.isNotBlank(defaultValue)) {
                        buffer.append(fieldEn + " " + fieldType + "(" + fieldLength + ")" + " NOT NULL DEFAULT '" + defaultValue + "',");
                    } else {
                        buffer.append(fieldEn + " " + fieldType + "(" + fieldLength + ")" + " NOT NULL,");
                    }
                } else {
                    buffer.append(fieldEn + " " + fieldType + "(" + fieldLength + "),");
                }
            }
        }
        buffer.append(");");
        //截取逗号
        int num = buffer.length();
        String sqlStr = buffer.substring(0, num - 3) + buffer.substring(num - 3).replaceFirst(buffer.substring(num - 3, num - 2), "");
        this.baseMapper.createTab(sqlStr);
    }



    @Override
    public Boolean addParent(PcafsDatabaseAddBo bo) {
        PcafsDatabase add = BeanUtil.toBean(bo, PcafsDatabase.class);
        add.setCreater(SecurityUtils.getUserId());
        return this.save(add);
    }

    @Override
    public List<TreeSelect> buildTree(List<PcafsDatabase> pcafsDatabase) {
        List<PcafsDatabase> trees = buildTreeSelect(pcafsDatabase);
        return trees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    public List<PcafsDatabase> buildTreeSelect(List<PcafsDatabase> pcafsDatabase) {
        List<PcafsDatabase> returnList = new ArrayList<>();
        List<Long> tempList = new ArrayList<>();
        for (PcafsDatabase e : pcafsDatabase) {
            tempList.add(e.getId());
        }
        for (Iterator<PcafsDatabase> iterator = pcafsDatabase.iterator(); iterator.hasNext(); ) {
            PcafsDatabase pd = iterator.next();
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(pd.getPid())) {
                recursionFn(pcafsDatabase, pd);
                returnList.add(pd);
            }
        }
        if (returnList.isEmpty()) {
            returnList = pcafsDatabase;
        }
        return returnList;
    }


    /**
     * 递归列表
     */
    private void recursionFn(List<PcafsDatabase> list, PcafsDatabase t) {
        // 得到子节点列表
        List<PcafsDatabase> childList = getChildList(list, t);
        t.setChildren(childList);
        for (PcafsDatabase tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<PcafsDatabase> list, PcafsDatabase t) {
        return getChildList(list, t).size() > 0 ? true : false;
    }

    /**
     * 得到子节点列表
     */
    private List<PcafsDatabase> getChildList(List<PcafsDatabase> list, PcafsDatabase t) {
        List<PcafsDatabase> tlist = new ArrayList<>();
        Iterator<PcafsDatabase> it = list.iterator();
        while (it.hasNext()) {
            PcafsDatabase n = it.next();
            if (Validator.isNotNull(n.getPid()) && n.getPid().longValue() == t.getId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    @Override
    public Boolean updateByEditBo(PcafsDatabaseEditBo bo) {
        PcafsDatabase update = BeanUtil.toBean(bo, PcafsDatabase.class);
        validEntityBeforeSave(update);
        return this.updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(PcafsDatabase entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        for (Long id : ids) {
            PcafsDatabase pcafsDatabase = this.baseMapper.selectById(id);
            String tabNameEn = pcafsDatabase.getTabNameEn();
            if(tabNameEn != null){
                this.baseMapper.dropTable(tabNameEn);
            }
        }
        return this.removeByIds(ids);
    }
}
